#ifndef _BUOLA_GUI_COCOA_CCOCOAWINDOW_H_
#define _BUOLA_GUI_COCOA_CCOCOAWINDOW_H_

#include "auto.h"
#include "cnsview.h"
#include <buola/gui/cphysicalwindow.h>

namespace buola { namespace gui { namespace cocoa {

DECLARE_NAME(Root)
    
///\addtogroup gui
///@{

///////////////////////////////////////////////////////////////////////////

/// cocoa physical window

/// objects of this class represent a window in the underlying windowing
/// system, such as an Xlib window
///
///////////////////////////////////////////////////////////////////////////

class CCocoaWindow : public CPhysicalWindow
{
public:
//! \name constructor and destructor
//@{
    CCocoaWindow(CWindow *pWindow);
    CCocoaWindow(NRoot);
    virtual ~CCocoaWindow();
//@}

public:
//! \name window creation and destruction
//@{
    //! from window information
    virtual void Create(CPhysicalWindow *pParent,const CPoint_d &pPos,const CSize_d &pSize);
    //! destroy the window
    virtual void Destroy();
//@}

//! \name direct protocol access
//! These functions provide direct access to the functionality of the
//! particular window environment. They should only be used by low-level
//! code.
//@{
    virtual void Freeze(bool pFrozen);
    virtual void ClearArea(const CRect_i &pR,bool);
    virtual void Map(bool pRaise);
    virtual void Unmap();
    virtual void Reparent(CPhysicalWindow*,const CPoint_d&);
    virtual void AddToSaveSet();
    virtual void Lower();
    virtual void Raise(const std::vector<CPhysicalWindow*> &pExc);
    virtual void StayOnTop(CPhysicalWindow *pOther);
    virtual void SelectInput(EEvents pEvents);
    virtual void SetGravity(int);
    virtual void SetBackingStore(bool);
    virtual void SetNoShape(int=SHAPE_BOUND);
    virtual void SetShape(const CRegion &pRegion,int=SHAPE_BOUND,const CPoint_d& =CPoint_d(nZero));
    virtual void SetShapeFromMask(img::CSurface *pMask,int=SHAPE_BOUND,const CPoint_d& =CPoint_d(nZero));
    virtual void SetShapeFromRect(const CRect_d&,int=SHAPE_BOUND,const CPoint_d& =CPoint_d(nZero));
    virtual void SetShapeFromWindow(CPhysicalWindow *pWindow,int=SHAPE_BOUND,const CPoint_d& =CPoint_d(nZero));
    virtual void SetPointer(PPointer pCursor);

    virtual void UpdateState();
    
    virtual CExposeHelper *GetExposeHelper();
//@}

//! \name window embedding
//@{
    virtual void Embed(CPhysicalWindow *pChild);
//@}

//! \name button grabbing
//@{
    virtual void GrabButton(EMouseButton pButton,EKeyMod pMods,bool pConfine,CPointer *pCursor);
    virtual void UngrabButton(EMouseButton pButton,EKeyMod pMods);
//@}

//! \name geometry
//@{
    virtual void Move(const CPoint_d&);
    virtual void Resize(const CSize_d&);
    virtual void MoveResize(const CPoint_d&,const CSize_d&);

    virtual CPoint_d TranslateCoords(const CPoint_d &pPoint,CPhysicalWindow *pWindow);

    virtual void SetFocus();
//@}

//! \name event management
//@{
    virtual void DispatchAll();
//@}

//! \name window-management
//@{
    virtual EWindowState GetState();
    virtual void Iconify(bool);
    virtual void Maximize(EWindowState);
    virtual void Shade(bool);
    virtual void Sticky(bool);
    virtual void SetDesktop(int);
    virtual void FullScreen(bool);
    virtual void StartMoveOperation(CMouseEvent *pE);
    virtual void StartResizeOperation(CMouseEvent *pE,EDragState pType);
    virtual void SetStrut(const CRect_d &pRect);
    virtual void SetOpacity(double pOpacity);
    virtual void SetTitle(const std::wstring &pTitle);
    virtual void SetIcon(PIcon pIcon);
    virtual void UpdateHints();
//@}

public:
//! \name inter-client communication
//@{
    virtual void SendSyntheticExposeEvent(const CRect_d &pRect);
    virtual void SendSyncRequest();
//@}

//! \name event handlers
//@{
    virtual void OnSizeHintsChanged();
    virtual void OnActivateForeign(bool pActivated);
//@}

    virtual int Depth()     {   return 32;  }
    virtual CSize_i SurfaceSize();
    virtual img::CGC *GetGC(img::EGCCaps pCaps=img::EGCCaps::NONE);
    virtual void BitBlt(const CPoint_d&,const CSize_d&,CSurface *pSrc,
                    const CPoint_d &pSrcOrigin,bool pExposures=false) {}

    CNSView *ContentView()  {   return mContentView;    }
    NSWindow *GetNSWindow() {   return mNSWindow;       }
    
    void DispatchDrawRect(const CRect_d &pRect);
    void DispatchGeometry();
    void DispatchButton(CMouseEvent::EType pType,EMouseButton pButton,NSEvent *pEvent);
    void DispatchMotion(NSEvent *pEvent);
    void DispatchWheel(NSEvent *pEvent);
    void DispatchKey(CKeyEvent::EType pType,NSEvent *pEvent);
    void DispatchModifier(NSEvent *pEvent);
    
private:
    NSWindow *mNSWindow;
    CNSView *mContentView;
    EKeyMod mLastModifiers;
    EMouseButton mPressedButtons;
    
    std::unique_ptr<CCocoaExposeHelper> mExposeHelper;
    bool mReportedVisibility;
};

///@}

/*namespace cocoa*/ } /*namespace gui*/ } /*namespace buola*/ }

#endif
